//
//  DMRewardedVideoManager.m
//  DualMediationSDK
//
//  Created by YeJary on 2025/7/9.
//

#import "DMRewardedVideoManager.h"
#import <IronSource/IronSource.h>
#import <UIKit/UIKit.h>
#import "IMLogUtils.h"
#import <AdjustSdk/AdjustSdk.h>
#import "DMConfigReader.h"
#import "IMSDKStartupConfigManager.h"
#import "DMThinkingManager.h"
#import "DMCommercialManager.h"

typedef NS_ENUM(NSInteger, WDRVState) { WDRVIdle, WDRVLoading, WDRVAvaliable, WDRVShowing };

@protocol LPMRewardedAdDelegate;
@class LPMRewardedAd, LPMAdInfo, LPMReward;

@interface DMRewardedVideoManager()<LPMRewardedAdDelegate>
@property (nonatomic, assign)BOOL receiveRewardForPlacement;
@property (nonatomic, assign) BOOL hasShowAd;
@property (nonatomic, strong) LPMRewardedAd *rewardedAd;
@property (nonatomic, strong) NSString *currentScene; // 当前展示的场景标识

// 事件打点相关属性
@property (nonatomic, assign) NSTimeInterval loadStartTime;
@property (nonatomic, copy) NSString *currentAdUnitId;
@property (nonatomic, copy) NSString *currentAdScene;

// 双广告位支持属性
@property (nonatomic, strong) LPMRewardedAd *primaryRewardedAd;
@property (nonatomic, strong) LPMRewardedAd *secondaryRewardedAd;
@property (nonatomic, assign) BOOL isLoadingPrimary;
@property (nonatomic, assign) BOOL isLoadingSecondary;

// ====== Watchdog 状态机与属性（与 WDRewardedVideoManager 风格一致） ======
@property (atomic, assign) WDRVState rvState;
@property (nonatomic, strong) LPMRewardedAd *currentShowingAd;     // 正在展示的对象（强引用）
@property (nonatomic, strong) LPMAdInfo *lastAdInfoForWatchdog;    // 兜底 close 用
@property (nonatomic, strong) NSTimer *rvClosePoller;              // 1s 轮询
@property (nonatomic, assign) NSTimeInterval rvClosePollDeadline;  // 截止时间戳
@property (nonatomic, assign) NSTimeInterval rvAbsoluteForceCloseDeadline; // 绝对兜底截止（防止无限等待）
@property (nonatomic, assign) BOOL rvBecameInactiveWhileShowing;   // 前后台：展示中离开
@property (nonatomic, assign) BOOL rvCameBackAfterClick;           // 前后台：点击后返回

@end

@implementation DMRewardedVideoManager
static DMRewardedVideoManager *_rewardedVideo = nil;
+ (instancetype)shareRewardedVideoManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _rewardedVideo = [[self alloc] init];
        [_rewardedVideo initializeDualAdSupport];
        [IMLogUtils info:IMLogTagSDKInit format:@"🎬 [Rewarded] 单例管理器创建成功，双广告位支持已初始化"];
    });
    return _rewardedVideo;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [IMLogUtils debug:IMLogTagSDKInit format:@"🎬 [Rewarded] Facebook计数队列创建成功"];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive) name:UIApplicationWillResignActiveNotification object:nil];
    }
    return self;
}

- (void)initializeDualAdSupport {
    // 检查是否启用双广告位配置
    self.isDualAdEnabled = [DMCommercialManager isDualAdEnabledForAdType:@"rewarded_video"];
    
    if (self.isDualAdEnabled) {
        self.currentPrimaryAdUnitId = [DMConfigReader primaryRewardAdUnitId];
        self.currentSecondaryAdUnitId = [DMConfigReader secondaryRewardAdUnitId];
        
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 双广告位模式启用"];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位ID: %@", self.currentPrimaryAdUnitId];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位ID: %@", self.currentSecondaryAdUnitId];
    } else {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 单广告位模式，保持原有逻辑"];
    }
    
    // 初始化状态
    self.isPrimaryAdLoaded = NO;
    self.isSecondaryAdLoaded = NO;
    self.isLoadingPrimary = NO;
    self.isLoadingSecondary = NO;
    self.primaryAdECPM = 0.0;
    self.secondaryAdECPM = 0.0;
    
    // 初始化重试设置
    [self initializeRetrySettings];
}

- (void)irDelegate
{
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 开始设置代理和初始化激励视频"];
    
    // 根据是否启用双广告位来选择加载方式
    if (self.isDualAdEnabled) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 使用双广告位加载模式"];
        [self loadDualRewardedAds];
    } else {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 使用单广告位加载模式"];
        [self loadRV];
    }
}

- (void)showIrSourceRV
{
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ========== 开始展示激励视频广告 =========="];
    [[NSUserDefaults standardUserDefaults] setObject:@"2" forKey:@"WDOrientation"];
    
    // 每次展示前重置奖励状态
    self.receiveRewardForPlacement = NO;
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重置奖励状态: receiveRewardForPlacement = NO"];
    
    
    // SDK_ad_show_request 广告展示请求事件打点
    NSDictionary *showRequestParams = @{
        @"w_ad_scene": @"rewarded_video_show",
        @"w_ad_type": @"rewarded_video"
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_request" properties:showRequestParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_show_request"];
    
    
    // ========== DMCommercialManager 策略控制 ==========
    DMCommercialManager *commercialSDK = [DMCommercialManager sharedInstance];
    
    // 选择最优广告位进行展示
    LPMRewardedAd *adToShow = nil;
    NSString *selectedAdUnitId = nil;
    
    if (self.isDualAdEnabled) {
        selectedAdUnitId = [self selectOptimalAdUnitId];
        
        // 应用FB策略控制 - 动态检查当前广告位是否应该展示
        BOOL isCurrentSecondary = [selectedAdUnitId isEqualToString:self.currentSecondaryAdUnitId];
        BOOL shouldShow = [commercialSDK shouldShowAd:selectedAdUnitId adType:@"rewarded_video" isSecondaryAdUnit:isCurrentSecondary];
        
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎯 FB策略检查：当前广告位 %@ (%@)", selectedAdUnitId, isCurrentSecondary ? @"备用" : @"主"];
        
        if (!shouldShow) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ⚠️ FB策略控制：当前%@广告位不应展示，尝试切换到另一个广告位", isCurrentSecondary ? @"备用" : @"主"];
            
            // 动态切换到另一个广告位
            NSString *alternativeAdUnitId;
            if ([selectedAdUnitId isEqualToString:self.currentPrimaryAdUnitId]) {
                alternativeAdUnitId = self.currentSecondaryAdUnitId;
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 从主广告位切换到备用广告位: %@", alternativeAdUnitId];
            } else {
                alternativeAdUnitId = self.currentPrimaryAdUnitId;
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 从备用广告位切换到主广告位: %@", alternativeAdUnitId];
            }
            
            // 检查切换后的广告位是否可以展示
            BOOL isAlternativeSecondary = [alternativeAdUnitId isEqualToString:self.currentSecondaryAdUnitId];
            BOOL alternativeShouldShow = [commercialSDK shouldShowAd:alternativeAdUnitId adType:@"rewarded_video" isSecondaryAdUnit:isAlternativeSecondary];
            
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎯 FB策略检查：切换后广告位 %@ (%@)", alternativeAdUnitId, isAlternativeSecondary ? @"备用" : @"主"];
            
            if (alternativeShouldShow) {
                selectedAdUnitId = alternativeAdUnitId;
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 切换成功：使用%@广告位进行展示", isAlternativeSecondary ? @"备用" : @"主"];
            } else {
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ❌ FB策略控制：所有广告位都不应展示，释放当前广告对象并重新加载"];
                [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:@{
                    @"w_ad_scene": self.currentAdScene ?: @"rewarded_video_show",
                    @"w_ad_type": @"rewarded_video",
                    @"w_error_code": @"10002",
                    @"w_error_msg": @"FB policy blocked all ad units"
                }];
                
                // 释放当前广告对象并重新加载
                [self cleanupAndReloadAdsWithReason:@"FB策略阻止所有广告位展示"];
                return;
            }
        } else {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ FB策略检查通过：当前%@广告位可以展示", isCurrentSecondary ? @"备用" : @"主"];
        }
        
        if ([selectedAdUnitId isEqualToString:self.currentPrimaryAdUnitId] && self.primaryRewardedAd && [self.primaryRewardedAd isAdReady]) {
            adToShow = self.primaryRewardedAd;
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择主广告位进行展示: %@", selectedAdUnitId];
        } else if ([selectedAdUnitId isEqualToString:self.currentSecondaryAdUnitId] && self.secondaryRewardedAd && [self.secondaryRewardedAd isAdReady]) {
            adToShow = self.secondaryRewardedAd;
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择备用广告位进行展示: %@", selectedAdUnitId];
        }
        self.currentAdUnitId = selectedAdUnitId;
    } else {
        // 单广告位模式，保持原有逻辑
        selectedAdUnitId = self.currentAdUnitId;
        
        // 应用FB策略控制 - 单广告位模式（主广告位）
        BOOL shouldShow = [commercialSDK shouldShowAd:selectedAdUnitId adType:@"rewarded_video" isSecondaryAdUnit:NO];
        if (!shouldShow) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ❌ FB策略控制：主广告位不应展示，释放当前广告对象并重新加载"];
            [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:@{
                @"w_ad_scene": self.currentAdScene ?: @"rewarded_video_show",
                @"w_ad_type": @"rewarded_video",
                @"w_error_code": @"10002",
                @"w_error_msg": @"FB policy blocked"
            }];
            
            // 释放当前广告对象并重新加载
            [self cleanupAndReloadAdsWithReason:@"FB策略阻止主广告位展示"];
            return;
        }
        
        adToShow = self.rewardedAd;
    }
    
    if (adToShow && [adToShow isAdReady])
    {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 激励视频广告准备就绪，开始展示"];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告实例: %@", adToShow];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告位ID: %@", selectedAdUnitId];
        
        UIViewController *rootViewController = [[[UIApplication sharedApplication].windows objectAtIndex:0] rootViewController];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 获取根控制器: %@", rootViewController];
        
        [adToShow showAdWithViewController:rootViewController placementName:NULL];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 调用 showAdWithViewController 完成"];
        // Watchdog：记录展示对象并进入展示状态
        self.currentShowingAd = adToShow;
        self.rvState = WDRVShowing;
        self.rvBecameInactiveWhileShowing = NO;
        self.rvCameBackAfterClick = NO;
    }else{
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ❌ 激励视频广告未准备就绪"];
        if (self.isDualAdEnabled) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位准备状态: %@", (self.primaryRewardedAd && [self.primaryRewardedAd isAdReady]) ? @"YES" : @"NO"];
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位准备状态: %@", (self.secondaryRewardedAd && [self.secondaryRewardedAd isAdReady]) ? @"YES" : @"NO"];
        } else {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告实例存在: %@", self.rewardedAd ? @"YES" : @"NO"];
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告是否就绪: %@", (self.rewardedAd && [self.rewardedAd isAdReady]) ? @"YES" : @"NO"];
        }
        
        // 上报SDK_ad_show_fail事件
        [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:@{
            @"w_ad_scene": self.currentAdScene ?: @"rewarded_video_show",
            @"w_ad_type": @"rewarded_video",
            @"w_error_code": @"10001",
            @"w_error_msg": @"Ad not ready"
        }];
        self.hasShowAd = YES;
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 设置 hasShowAd = YES，将在广告加载完成后自动展示"];
        
        // 根据双广告位模式选择重新加载方式
        if (self.isDualAdEnabled) {
            [self loadDualRewardedAds];
        } else {
            [self loadRV];
        }
    }
}

#pragma mark - 场景化激励视频接口

- (void)showIrSourceRVForScene:(NSString *)scene
{
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ========== 开始展示场景化激励视频广告 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 场景标识: %@", scene ?: @"未指定场景"];
    
    // 保存当前场景标识
    self.currentScene = scene;
    
    [[NSUserDefaults standardUserDefaults] setObject:@"2" forKey:@"WDOrientation"];
    
    // 每次展示前重置奖励状态
    self.receiveRewardForPlacement = NO;
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重置奖励状态: receiveRewardForPlacement = NO"];
    
    // SDK_ad_show_request 广告展示请求事件打点
    NSDictionary *showRequestParams = @{
        @"w_ad_scene": scene ?: @"rewarded_video_show",
        @"w_ad_type": @"rewarded_video"
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_request" properties:showRequestParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_show_request (场景: %@)", scene];
    
    
    // ========== DMCommercialManager 策略控制 ==========
    DMCommercialManager *commercialSDK = [DMCommercialManager sharedInstance];
    
    // 选择最优广告位进行展示
    LPMRewardedAd *adToShow = nil;
    NSString *selectedAdUnitId = nil;
    
    if (self.isDualAdEnabled) {
        selectedAdUnitId = [self selectOptimalAdUnitId];
        
        // 应用FB策略控制 - 动态检查当前广告位是否应该展示
        BOOL isCurrentSecondary = [selectedAdUnitId isEqualToString:self.currentSecondaryAdUnitId];
        BOOL shouldShow = [commercialSDK shouldShowAd:selectedAdUnitId adType:@"rewarded_video" isSecondaryAdUnit:isCurrentSecondary];
        
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎯 FB策略检查：当前广告位 %@ (%@)", selectedAdUnitId, isCurrentSecondary ? @"备用" : @"主"];
        
        if (!shouldShow) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ⚠️ FB策略控制：当前%@广告位不应展示，尝试切换到另一个广告位", isCurrentSecondary ? @"备用" : @"主"];
            
            // 动态切换到另一个广告位
            NSString *alternativeAdUnitId;
            if ([selectedAdUnitId isEqualToString:self.currentPrimaryAdUnitId]) {
                alternativeAdUnitId = self.currentSecondaryAdUnitId;
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 从主广告位切换到备用广告位: %@", alternativeAdUnitId];
            } else {
                alternativeAdUnitId = self.currentPrimaryAdUnitId;
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 从备用广告位切换到主广告位: %@", alternativeAdUnitId];
            }
            
            // 检查切换后的广告位是否可以展示
            BOOL isAlternativeSecondary = [alternativeAdUnitId isEqualToString:self.currentSecondaryAdUnitId];
            BOOL alternativeShouldShow = [commercialSDK shouldShowAd:alternativeAdUnitId adType:@"rewarded_video" isSecondaryAdUnit:isAlternativeSecondary];
            
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎯 FB策略检查：切换后广告位 %@ (%@)", alternativeAdUnitId, isAlternativeSecondary ? @"备用" : @"主"];
            
            if (alternativeShouldShow) {
                selectedAdUnitId = alternativeAdUnitId;
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 切换成功：使用%@广告位进行展示", isAlternativeSecondary ? @"备用" : @"主"];
            } else {
                [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ❌ FB策略控制：所有广告位都不应展示，释放当前广告对象并重新加载"];
                [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:@{
                    @"w_ad_scene": self.currentAdScene ?: @"rewarded_video_show",
                    @"w_ad_type": @"rewarded_video",
                    @"w_error_code": @"10002",
                    @"w_error_msg": @"FB policy blocked all ad units"
                }];
                
                // 释放当前广告对象并重新加载
                [self cleanupAndReloadAdsWithReason:@"FB策略阻止所有广告位展示"];
                return;
            }
        } else {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ FB策略检查通过：当前%@广告位可以展示", isCurrentSecondary ? @"备用" : @"主"];
        }
        
        if ([selectedAdUnitId isEqualToString:self.currentPrimaryAdUnitId] && self.primaryRewardedAd && [self.primaryRewardedAd isAdReady]) {
            adToShow = self.primaryRewardedAd;
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择主广告位进行展示: %@", selectedAdUnitId];
        } else if ([selectedAdUnitId isEqualToString:self.currentSecondaryAdUnitId] && self.secondaryRewardedAd && [self.secondaryRewardedAd isAdReady]) {
            adToShow = self.secondaryRewardedAd;
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择备用广告位进行展示: %@", selectedAdUnitId];
        }
        self.currentAdUnitId = selectedAdUnitId;
    } else {
        // 单广告位模式，保持原有逻辑
        selectedAdUnitId = self.currentAdUnitId;
        
        // 应用FB策略控制 - 单广告位模式（主广告位）
        BOOL shouldShow = [commercialSDK shouldShowAd:selectedAdUnitId adType:@"rewarded_video" isSecondaryAdUnit:NO];
        if (!shouldShow) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ❌ FB策略控制：主广告位不应展示，释放当前广告对象并重新加载"];
            [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:@{
                @"w_ad_scene": self.currentAdScene ?: @"rewarded_video_show",
                @"w_ad_type": @"rewarded_video",
                @"w_error_code": @"10002",
                @"w_error_msg": @"FB policy blocked"
            }];
            
            // 释放当前广告对象并重新加载
            [self cleanupAndReloadAdsWithReason:@"FB策略阻止主广告位展示"];
            return;
        }
        
        adToShow = self.rewardedAd;
    }
    
    if (adToShow && [adToShow isAdReady])
    {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 激励视频广告准备就绪，开始展示"];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告实例: %@", adToShow];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告位ID: %@", selectedAdUnitId];
        
        UIViewController *rootViewController = [[[UIApplication sharedApplication].windows objectAtIndex:0] rootViewController];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 获取根控制器: %@", rootViewController];
        
        [adToShow showAdWithViewController:rootViewController placementName:scene];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 调用 showAdWithViewController 完成"];
        // Watchdog：记录展示对象并进入展示状态
        self.currentShowingAd = adToShow;
        self.rvState = WDRVShowing;
        self.rvBecameInactiveWhileShowing = NO;
        self.rvCameBackAfterClick = NO;
    }else{
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ❌ 激励视频广告未准备就绪"];
        if (self.isDualAdEnabled) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位准备状态: %@", (self.primaryRewardedAd && [self.primaryRewardedAd isAdReady]) ? @"YES" : @"NO"];
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位准备状态: %@", (self.secondaryRewardedAd && [self.secondaryRewardedAd isAdReady]) ? @"YES" : @"NO"];
        } else {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告实例存在: %@", self.rewardedAd ? @"YES" : @"NO"];
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告是否就绪: %@", (self.rewardedAd && [self.rewardedAd isAdReady]) ? @"YES" : @"NO"];
        }
        
        // 上报SDK_ad_show_fail事件
        [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:@{
            @"w_ad_scene": self.currentAdScene ?: @"rewarded_video_show",
            @"w_ad_type": @"rewarded_video",
            @"w_error_code": @"10001",
            @"w_error_msg": @"Ad not ready"
        }];
        self.hasShowAd = YES;
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 设置 hasShowAd = YES，将在广告加载完成后自动展示"];
        
        // 根据双广告位模式选择重新加载方式
        if (self.isDualAdEnabled) {
            [self loadDualRewardedAds];
        } else {
            [self loadRV];
        }
    }
}

- (BOOL)isRewardedVideoReadyForScene:(NSString *)scene
{
    BOOL isReady = (self.rewardedAd && [self.rewardedAd isAdReady]);
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 检查场景化激励视频广告状态 (场景: %@): %@", scene ?: @"未指定场景", isReady ? @"就绪" : @"未就绪"];
    return isReady;
}


- (void)loadRV
{
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ========== 开始加载激励视频广告 =========="];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 埋点事件已发送: adLoad"];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        // 创建 LPMRewardedAd
        NSString *adUnitId = [[DMConfigReader sharedInstance]rewardedAdConfigs][0].ad_unitID;
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 创建 LPMRewardedAd 实例"];
        [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdUnit ID: %@", adUnitId];
        
        [[DMCommercialManager sharedInstance] recordAdLoadRequest:adUnitId adType:@"rewarded_video"];
        
        self.rewardedAd = [[LPMRewardedAd alloc] initWithAdUnitId:adUnitId];
        [self.rewardedAd setDelegate:self];
        [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 设置代理完成: %@", self];
        
        [self.rewardedAd loadAd];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 调用 loadAd 开始加载广告"];
    });
}

#pragma mark - LPMRewardedAdDelegate

- (void)didLoadAdWithAdInfo:(LPMAdInfo *)adInfo {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ ========== 激励视频加载成功 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdInfo详情:"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - AdNetwork: %@", adInfo.adNetwork ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - AdUnit: %@", adInfo.adUnitId ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceId: %@", adInfo.instanceId ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceName: %@", adInfo.instanceName ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - Revenue: $%.6f", adInfo.revenue ? adInfo.revenue.doubleValue : 0.0];
    
    // 记录广告网络信息到DMCommercialManager
    if (adInfo.adNetwork && adInfo.adUnitId) {
        [[DMCommercialManager sharedInstance] recordAdNetworkInfo:adInfo.adNetwork adUnitId:adInfo.adUnitId];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 📝 已记录广告网络信息: %@ -> %@", adInfo.adUnitId, adInfo.adNetwork];
    } else {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ⚠️ 广告网络信息不完整，无法记录: adNetwork=%@, adUnitId=%@", adInfo.adNetwork, adInfo.adUnitId];
    }
    
    // 计算填充时间
    NSTimeInterval fillTime = [[NSDate date] timeIntervalSince1970] - self.loadStartTime;
    
    // 判断是主广告位还是备用广告位加载成功
    BOOL isPrimaryAd = [adInfo.adUnitId isEqualToString:self.currentPrimaryAdUnitId];
    BOOL isSecondaryAd = [adInfo.adUnitId isEqualToString:self.currentSecondaryAdUnitId];
    
    if (self.isDualAdEnabled && isPrimaryAd) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位加载成功"];
        self.isPrimaryAdLoaded = YES;
        self.isLoadingPrimary = NO;
        self.primaryAdECPM = adInfo.revenue ? adInfo.revenue.doubleValue : 0.0;
        self.primaryAdLoadTime = fillTime;
    } else if (self.isDualAdEnabled && isSecondaryAd) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位加载成功"];
        self.isSecondaryAdLoaded = YES;
        self.isLoadingSecondary = NO;
        self.secondaryAdECPM = adInfo.revenue ? adInfo.revenue.doubleValue : 0.0;
        self.secondaryAdLoadTime = fillTime;
    } else {
        // 单广告位模式
        self.currentAdUnitId = adInfo.adUnitId;
    }
    
    // 上报SDK_ad_fill_success事件
    NSString *adSource = @"single";
    if (self.isDualAdEnabled) {
        adSource = isPrimaryAd ? @"primary" : (isSecondaryAd ? @"secondary" : @"unknown");
    }
    
    // SDK_ad_fill_success 广告填充成功事件打点
    NSDictionary *fillSuccessParams = @{
        @"w_fill_time": @((NSInteger)(fillTime * 1000)), // 转换为毫秒
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": adInfo.adUnitId ?: @"",
        @"w_network": adInfo.adNetwork ?: @"",
        @"w_ad_source": adSource
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_fill_success" properties:fillSuccessParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_fill_success"];
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 埋点事件已发送: adLoadFillSuccess"];
    
    // 广告加载成功，更新统计并重置重试状态
    self.totalLoadAttempts++;
    [self resetRetryState];
    
    double successRate = 1.0 - [self calculateFailureRate];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 加载成功统计 - 总尝试: %ld, 成功率: %.2f%%",
          (long)self.totalLoadAttempts, successRate * 100];
    
    // 通知统一代理
    if (self.delegate && [self.delegate respondsToSelector:@selector(dmAdManager:didLoadAd:adType:)]) {
        [self.delegate dmAdManager:(id)self didLoadAd:adInfo.adUnitId adType:@"rewarded_video"];
    }
    
    if (self.hasShowAd)
    {
        self.hasShowAd = NO;
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 检测到延迟展示标志，立即展示广告"];
        [self showIrSourceRV];
    }
}

- (void)didFailToLoadAdWithAdUnitId:(NSString *)adUnitId error:(NSError *)error {
    [IMLogUtils warning:IMLogTagAd format:@"🎬 [Rewarded] ❌ ========== 激励视频加载失败 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdUnit ID: %@", adUnitId];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 错误信息: %@", error.localizedDescription];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 错误代码: %ld", (long)error.code];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 错误域: %@", error.domain];
    if (error.userInfo) {
        [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 错误详情: %@", error.userInfo];
    }
    // 计算填充时间
    NSTimeInterval fillTime = [[NSDate date] timeIntervalSince1970] - self.loadStartTime;
    
    // 判断是主广告位还是备用广告位加载失败
    BOOL isPrimaryAd = [adUnitId isEqualToString:self.currentPrimaryAdUnitId];
    BOOL isSecondaryAd = [adUnitId isEqualToString:self.currentSecondaryAdUnitId];
    
    if (self.isDualAdEnabled && isPrimaryAd) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位加载失败"];
        self.isLoadingPrimary = NO;
        self.isPrimaryAdLoaded = NO;
        
        // 如果备用广告位已就绪，切换到备用广告位
        if (self.isSecondaryAdLoaded) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位失败，切换到备用广告位"];
            [self switchToSecondaryAdIfNeeded];
        }
    } else if (self.isDualAdEnabled && isSecondaryAd) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位加载失败"];
        self.isLoadingSecondary = NO;
        self.isSecondaryAdLoaded = NO;
    }
    
    // 上报SDK_ad_fill_fail事件
    NSString *adSource = @"single";
    if (self.isDualAdEnabled) {
        adSource = isPrimaryAd ? @"primary" : (isSecondaryAd ? @"secondary" : @"unknown");
    }
    
    // SDK_ad_fill_fail 广告填充失败事件打点
    NSDictionary *fillFailParams = @{
        @"w_fill_time": @((NSInteger)(fillTime * 1000)), // 转换为毫秒
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": adUnitId ?: @"",
        @"w_error_code": @(error.code),
        @"w_error_msg": error.localizedDescription ?: @"",
        @"w_ad_source": adSource
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_fill_fail" properties:fillFailParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_fill_fail"];
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 5秒后重新尝试加载..."];
    // 更新失败统计
    [self updateFailureStatistics];
    
    // 只有在双广告位都失败或单广告位失败时才考虑重试
    BOOL shouldConsiderRetry = YES;
    if (self.isDualAdEnabled) {
        // 如果是双广告位模式，只有当两个广告位都失败且都不在加载中时才考虑重试
        if ((isPrimaryAd && (self.isSecondaryAdLoaded || self.isLoadingSecondary)) ||
            (isSecondaryAd && (self.isPrimaryAdLoaded || self.isLoadingPrimary))) {
            shouldConsiderRetry = NO;
        }
    }
    
    if (shouldConsiderRetry && [self shouldRetry]) {
        NSTimeInterval retryDelay = [self calculateRetryDelay];
        [self scheduleRetryWithDelay:retryDelay];
    } else if (shouldConsiderRetry) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试条件不满足，停止重试"];
    }
}

- (void)didDisplayAdWithAdInfo:(LPMAdInfo *)adInfo {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ ========== 激励视频展示成功 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdInfo详情:"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - AdNetwork: %@", adInfo.adNetwork ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceId: %@", adInfo.instanceId ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceName: %@", adInfo.instanceName ?: @"N/A"];
    
    // 场景化回调转发
    if (self.delegate && [self.delegate respondsToSelector:@selector(dmAdManager:didShowRewardedVideoForScene:adId:)]) {
        [self.delegate dmAdManager:nil didShowRewardedVideoForScene:self.currentScene adId:adInfo.instanceId ?: @"unknown"];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 场景化回调转发: didShowRewardedVideoForScene (场景: %@)", self.currentScene];
    }
    
    // Facebook广告展示统计记录
    if ([self isFacebookAd:adInfo]) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎯 检测到Facebook广告展示，记录统计数据"];
        [[DMCommercialManager sharedInstance] recordFacebookAdShow];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ Facebook广告展示统计已记录"];
    }
    
    // SDK_ad_show_success 广告展示成功事件打点
    NSDictionary *showSuccessParams = @{
        @"w_ad_scene": self.currentScene ?: @"rewarded_video_show",
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": adInfo.adUnitId ?: @"",
        @"w_network": adInfo.adNetwork ?: @"",
        @"w_ad_revenue": adInfo.revenue ?: @(0.0)
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_success" properties:showSuccessParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_show_success"];
    
    // AD_RV_show 激励视频广告展示事件上报
    double ecpm = adInfo.revenue ? adInfo.revenue.doubleValue * 1000 : 0.0;
    NSDictionary *rvShowParams = @{
        @"w_revenue": @(ecpm)
    };
    [[DMThinkingManager shareThinkingManager] thinkingTrackEventWithKey:@"AD_RV_show" jsonStr:rvShowParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件上报: AD_RV_show, w_revenue: %.2f", ecpm];
    
    // 收入上报处理
    double revenueUSD = [[NSUserDefaults standardUserDefaults] doubleForKey:@"Banner_RevenueUSD"];
    if (revenueUSD > 0) {
        NSNumber *revenue = [NSNumber numberWithDouble:revenueUSD * 1000];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 💰 开始收入上报:"];
        [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - 原始收入: $%.6f", revenueUSD];
        [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - 上报收入: %@ (micros)", revenue];

        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] Taichi 收入上报完成"];
        
        // Adjust 收入上报
        ADJAdRevenue *adjustAdRevenue = [[ADJAdRevenue alloc] initWithSource:@"ironsource_sdk"];
        [adjustAdRevenue setRevenue:revenueUSD currency:@"USD"];
        [adjustAdRevenue setAdRevenueNetwork:adInfo.adNetwork];
        [adjustAdRevenue setAdRevenueUnit:adInfo.adUnitId];
        [adjustAdRevenue setAdRevenuePlacement:adInfo.placementName];
        
        [adjustAdRevenue addPartnerParameter:@"ad_format" value: adInfo.adUnitId];
        [adjustAdRevenue addPartnerParameter:@"ad_unit_id" value: adInfo.instanceId];
        [adjustAdRevenue addPartnerParameter:@"auctionId" value:adInfo.auctionId];

        [Adjust trackAdRevenue:adjustAdRevenue];
        [IMLogUtils info:IMLogTagAd format:@"�� [Rewarded] Adjust 收入上报完成"];
        
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] IronSource IAA 收入上报完成"];
    } else {
        [IMLogUtils warning:IMLogTagAd format:@"🎬 [Rewarded] ⚠️ 广告收入为0，跳过收入上报"];
    }
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 回调通知: Show"];
    // Watchdog：启动关闭兜底轮询（20s，与WD保持一致）
    self.rvState = WDRVShowing;
    self.lastAdInfoForWatchdog = adInfo;
    [self startRVCloseWatchdogWithTimeout:20 adInfo:adInfo];
}

- (void)didFailToDisplayAdWithAdInfo:(LPMAdInfo *)adInfo error:(NSError *)error {
    [IMLogUtils warning:IMLogTagAd format:@"🎬 [Rewarded] ❌ ========== 激励视频展示失败 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdInfo: %@", adInfo];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 错误信息: %@", error.localizedDescription];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 错误代码: %ld", (long)error.code];
    
    // 场景化失败回调转发
    if (self.delegate && [self.delegate respondsToSelector:@selector(dmAdManager:didFailToShowRewardedVideoForScene:error:)]) {
        [self.delegate dmAdManager:nil didFailToShowRewardedVideoForScene:self.currentScene error:error];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 场景化回调转发: didFailToShowRewardedVideoForScene (场景: %@)", self.currentScene];
    }
    // 重置场景标识
    self.currentScene = nil;
    
    // 更新失败统计
    [self updateFailureStatistics];
   
    // SDK_ad_show_fail 广告展示失败事件打点
    NSDictionary *showFailParams = @{
        @"w_ad_scene": self.currentScene ?: @"rewarded_video_show",
        @"w_ad_type": @"rewarded_video",
        @"w_error_code": [NSString stringWithFormat:@"%ld", (long)error.code],
        @"w_error_msg": error.localizedDescription ?: @""
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_fail" properties:showFailParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_show_fail"];
    
    // Watchdog：展示失败，停止兜底轮询并重置状态
    [self invalidateRVCloseWatchdog];
    self.rvState = WDRVIdle;
    self.currentShowingAd = nil;
    self.rvBecameInactiveWhileShowing = NO;
    self.rvCameBackAfterClick = NO;
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重新加载广告..."];
    // 使用智能重试机制
    if ([self shouldRetry]) {
        NSTimeInterval retryDelay = [self calculateRetryDelay];
        [self scheduleRetryWithDelay:retryDelay];
    } else {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试条件不满足，停止重试"];
    }
}

- (void)didClickAdWithAdInfo:(LPMAdInfo *)adInfo {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 👆 ========== 激励视频广告被点击 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdInfo详情:"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - AdNetwork: %@", adInfo.adNetwork ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceId: %@", adInfo.instanceId ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceName: %@", adInfo.instanceName ?: @"N/A"];
    
    
    // Facebook广告点击率控制策略
    if ([self isFacebookAd:adInfo]) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎯 检测到Facebook广告点击，记录统计数据"];
        [[DMCommercialManager sharedInstance] recordFacebookAdClick];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ Facebook广告点击统计已记录"];
    }
    
    // SDK_ad_show_click 广告点击事件打点
    NSDictionary *clickParams = @{
        @"w_ad_scene": self.currentScene ?: @"rewarded_video_show",
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": adInfo.adUnitId ?: @"",
        @"w_network": adInfo.adNetwork ?: @"",
        @"w_ad_revenue": adInfo.revenue ?: @(0.0)
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_click" properties:clickParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_show_click"];
    
    // Watchdog：点击后等待返回再判断
    self.rvCameBackAfterClick = NO;
}

- (void)didCloseAdWithAdInfo:(LPMAdInfo *)adInfo {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 ========== 激励视频广告关闭 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] AdInfo: %@", adInfo];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 当前奖励状态: %@", self.receiveRewardForPlacement ? @"已获得奖励" : @"未获得奖励"];
    
    // Watchdog：广告关闭，停止兜底轮询并重置状态
    [self invalidateRVCloseWatchdog];
    self.rvState = WDRVIdle;
    self.currentShowingAd = nil;
    self.rvBecameInactiveWhileShowing = NO;
    self.rvCameBackAfterClick = NO;
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 埋点事件已发送: adClose"];
    
    // 场景化关闭回调转发
    if (self.delegate && [self.delegate respondsToSelector:@selector(dmAdManager:didCloseRewardedVideoForScene:adId:isUserRewarded:)]) {
        [self.delegate dmAdManager:nil didCloseRewardedVideoForScene:self.currentScene adId:adInfo.instanceId ?: @"unknown" isUserRewarded:self.receiveRewardForPlacement];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 场景化回调转发: didCloseRewardedVideoForScene (场景: %@, 奖励: %@)", self.currentScene, self.receiveRewardForPlacement ? @"是" : @"否"];
    }
    // 重置场景标识
    self.currentScene = nil;
    
    // 如果没有获得奖励，发送 Close 回调
    // Finish 回调已经在 didRewardAdWithAdInfo:reward: 中处理
    if (!self.receiveRewardForPlacement)
    {
        
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 回调通知: Close (未获得奖励)"];
    } else {
       
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 回调通知: Finish12 回调已在奖励方法中发送"];
    }
    
    // 重置状态并重新加载
    self.receiveRewardForPlacement = NO;
    self.hasShowAd = NO;
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 状态重置完成: receiveRewardForPlacement=NO, hasShowAd=NO"];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 开始重新加载下一个广告..."];
    // 使用智能重试机制重新加载下一个广告
    if ([self shouldRetry]) {
        NSTimeInterval retryDelay = [self calculateRetryDelay];
        [self scheduleRetryWithDelay:retryDelay];
    } else {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试条件不满足，停止重试"];
    }
}

- (void)didRewardAdWithAdInfo:(nonnull LPMAdInfo *)adInfo reward:(nonnull LPMReward *)reward {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🎉 ========== 激励视频奖励成功！ =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 🎁 奖励详情:"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - 奖励名称: %@", reward.name ?: @"DefaultReward"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - 奖励数量: %ld", (long)reward.amount];
    
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 📊 AdInfo详情:"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - AdNetwork: %@", adInfo.adNetwork ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - AdUnit: %@", adInfo.adUnitId ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceId: %@", adInfo.instanceId ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - InstanceName: %@", adInfo.instanceName ?: @"N/A"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded]   - Revenue: $%.6f", adInfo.revenue ? adInfo.revenue.doubleValue : 0.0];
    
    // 设置奖励标志
    self.receiveRewardForPlacement = YES;
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 设置奖励标志: receiveRewardForPlacement = YES"];
    
    // SDK_ad_show_completed 广告播放完成事件打点
    NSDictionary *showCompletedParams = @{
        @"w_ad_scene": self.currentScene ?: @"rewarded_video_show",
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": adInfo.adUnitId ?: @"",
        @"w_network": adInfo.adNetwork ?: @"",
        @"w_ad_revenue": adInfo.revenue ?: @(0.0)
    };
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_show_completed" properties:showCompletedParams];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件打点: SDK_ad_show_completed"];
    // Watchdog：发奖后缩短关闭窗口
    [self restartRVCloseWatchdogWithTimeout:12 adInfo:adInfo];
    
    // 直接在奖励回调中调用 Finish，确保时序正确
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 回调通知: Finish13 (奖励成功)"];
    
    // AD_RV_Completed 激励视频播放完成事件上报（场景+收入，收入单位mUSD）
    {
        double ecpm = adInfo.revenue ? adInfo.revenue.doubleValue * 1000.0 : 0.0;
        NSString *scene = self.currentScene ?: @"rewarded_video_show";
        NSDictionary *rvCompletedParams = @{ @"w_scene": scene, @"w_revenue": @(ecpm) };
        [[DMThinkingManager shareThinkingManager] thinkingTrackEventWithKey:@"AD_RV_Completed" jsonStr:rvCompletedParams];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 事件上报: AD_RV_Completed, w_scene=%@, w_revenue: %.2f", scene, ecpm];
    }
    
    
}

// 注意：didRewardUserWithAdInfo 是旧版本的回调方法
// 新版本的 LPM SDK 使用 didRewardAdWithAdInfo:reward: 方法
// 保留此方法作为兼容性备用，但主要逻辑已迁移到新方法
- (void)didRewardUserWithAdInfo:(LPMAdInfo *)adInfo {
    [IMLogUtils warning:IMLogTagAd format:@"🎬 [Rewarded] ⚠️ ========== 旧版本奖励回调被调用 =========="];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 这是备用兼容方法 didRewardUserWithAdInfo"];
    [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 当前奖励状态: %@", self.receiveRewardForPlacement ? @"已获得奖励" : @"未获得奖励"];
    
    // 如果新的奖励回调没有被调用，则使用此备用方案
    if (!self.receiveRewardForPlacement) {
        self.receiveRewardForPlacement = YES;
//        [[WDCallBackManager shareCallBackManager] adCallBackWithType:Finish adSpace:[WDCallBackModel shareCallBackModel].adSpace message:@""];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 使用备用奖励回调方法，设置奖励状态并发送 回调通知: Finish11"];
    } else {
        [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] 新版奖励回调已处理，跳过备用方案"];
    }
}

#pragma mark - 内存管理和重新加载

/**
 * 清理当前广告对象并重新加载
 * @param reason 清理原因，用于日志记录
 */
- (void)cleanupAndReloadAdsWithReason:(NSString *)reason {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🧹 ========== 开始清理广告对象 ==========="];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 清理原因: %@", reason ?: @"未知原因"];
    
    if (self.isDualAdEnabled) {
        // 双广告位模式：释放主广告位和备用广告位
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 双广告位模式：释放主广告位和备用广告位"];
        
        if (self.primaryRewardedAd) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 释放主广告位对象: %@", self.currentPrimaryAdUnitId];
            [self.primaryRewardedAd setDelegate:nil];
            self.primaryRewardedAd = nil;
        }
        
        if (self.secondaryRewardedAd) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 释放备用广告位对象: %@", self.currentSecondaryAdUnitId];
            [self.secondaryRewardedAd setDelegate:nil];
            self.secondaryRewardedAd = nil;
        }
        
        // 重置双广告位相关状态标志
        self.isPrimaryAdLoaded = NO;
        self.isSecondaryAdLoaded = NO;
        self.isLoadingPrimary = NO;
        self.isLoadingSecondary = NO;
        self.primaryAdECPM = 0.0;
        self.secondaryAdECPM = 0.0;
        self.primaryAdLoadTime = 0.0;
        self.secondaryAdLoadTime = 0.0;
        
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 双广告位状态已重置"];
        
        // 重新加载双广告位
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 开始重新加载双广告位"];
        [self loadDualRewardedAds];
        
    } else {
        // 单广告位模式：释放单个广告位
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 单广告位模式：释放广告位对象"];
        
        if (self.rewardedAd) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 释放广告位对象: %@", self.currentAdUnitId];
            [self.rewardedAd setDelegate:nil];
            self.rewardedAd = nil;
        }
        
        // 重新加载单广告位
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 🔄 开始重新加载单广告位"];
        [self loadRV];
    }
    
    // 重置通用状态
    self.hasShowAd = NO;
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ✅ 广告对象清理和重新加载完成"];
}

#pragma mark - Facebook广告识别

/**
 * 判断是否为Facebook广告源
 * @param adInfo 广告信息对象
 * @return YES表示是Facebook广告，NO表示不是
 */
- (BOOL)isFacebookAd:(LPMAdInfo *)adInfo {
    if (!adInfo || !adInfo.adNetwork) {
        return NO;
    }
    
    NSString *adNetwork = [adInfo.adNetwork lowercaseString];
    return [adNetwork containsString:@"facebook"] ||
           [adNetwork containsString:@"meta"] ||
           [adNetwork containsString:@"fb"];
}

#pragma mark - 双广告位支持方法

- (void)loadDualRewardedAds {
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ========== 开始双广告位加载 =========="];
    
    if (!self.isDualAdEnabled) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 双广告位未启用，回退到单广告位模式"];
        [self loadRV];
        return;
    }
    
    // 记录加载开始时间
    self.loadStartTime = [[NSDate date] timeIntervalSince1970];
    self.primaryAdLoadTime = self.loadStartTime;
    self.secondaryAdLoadTime = self.loadStartTime;
    
    // 并行加载主广告位和备用广告位
    [self loadPrimaryRewardedAd];
    [self loadSecondaryRewardedAd];
}

- (void)loadPrimaryRewardedAd {
    if (self.isLoadingPrimary || !self.currentPrimaryAdUnitId) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位正在加载中或ID为空，跳过"];
        return;
    }
    
    self.isLoadingPrimary = YES;
    self.isPrimaryAdLoaded = NO;
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 开始加载主广告位: %@", self.currentPrimaryAdUnitId];
    
    // 记录广告加载请求到DMCommercialManager
    [[DMCommercialManager sharedInstance] recordAdLoadRequest:self.currentPrimaryAdUnitId adType:@"rewarded_video"];
    
    // 上报SDK_ad_fill_request事件
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_fill_request" properties:@{
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": self.currentPrimaryAdUnitId,
        @"w_ad_source": @"primary"
    }];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        self.primaryRewardedAd = [[LPMRewardedAd alloc] initWithAdUnitId:self.currentPrimaryAdUnitId];
        [self.primaryRewardedAd setDelegate:self];
        [self.primaryRewardedAd loadAd];
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位开始加载"];
    });
}

- (void)loadSecondaryRewardedAd {
    if (!self.currentSecondaryAdUnitId || self.isLoadingSecondary) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位ID为空或正在加载中，跳过加载"];
        return;
    }
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 开始加载备用广告位: %@", self.currentSecondaryAdUnitId];
    self.isLoadingSecondary = YES;
    
    // 记录广告加载请求到DMCommercialManager
    [[DMCommercialManager sharedInstance] recordAdLoadRequest:self.currentSecondaryAdUnitId adType:@"rewarded_video"];
    
    // 上报SDK_ad_fill_request事件
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_ad_fill_request" properties:@{
        @"w_ad_type": @"rewarded_video",
        @"w_ad_unit_id": self.currentSecondaryAdUnitId,
        @"w_ad_source": @"secondary"
    }];
    
    self.secondaryRewardedAd = [[LPMRewardedAd alloc] initWithAdUnitId:self.currentSecondaryAdUnitId];
    self.secondaryRewardedAd.delegate = self;
    [self.secondaryRewardedAd loadAd];
}

- (NSString *)selectOptimalAdUnitId {
    if (!self.isDualAdEnabled) {
        return [DMConfigReader primaryRewardAdUnitId];
    }
    
    // 检查广告位可用性
    BOOL primaryReady = self.isPrimaryAdLoaded && self.primaryRewardedAd && [self.primaryRewardedAd isAdReady];
    BOOL secondaryReady = self.isSecondaryAdLoaded && self.secondaryRewardedAd && [self.secondaryRewardedAd isAdReady];
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 广告位状态检查:"];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位就绪: %@, ECPM: %.6f", primaryReady ? @"YES" : @"NO", self.primaryAdECPM];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 备用广告位就绪: %@, ECPM: %.6f", secondaryReady ? @"YES" : @"NO", self.secondaryAdECPM];
    
    // 如果两个广告位都准备就绪，根据ECPM选择
    if (primaryReady && secondaryReady) {
        if (self.primaryAdECPM >= self.secondaryAdECPM) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择主广告位 (ECPM更高: %.6f >= %.6f)", self.primaryAdECPM, self.secondaryAdECPM];
            return self.currentPrimaryAdUnitId;
        } else {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择备用广告位 (ECPM更高: %.6f > %.6f)", self.secondaryAdECPM, self.primaryAdECPM];
            return self.currentSecondaryAdUnitId;
        }
    }
    
    // 如果只有一个广告位准备就绪，选择可用的
    if (primaryReady) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择主广告位 (仅主广告位可用)"];
        return self.currentPrimaryAdUnitId;
    }
    
    if (secondaryReady) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 选择备用广告位 (仅备用广告位可用)"];
        return self.currentSecondaryAdUnitId;
    }
    
    // 如果都不可用，默认返回主广告位ID
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 无可用广告位，默认返回主广告位ID"];
    return self.currentPrimaryAdUnitId;
}

- (void)switchToSecondaryAdIfNeeded {
    if (!self.isDualAdEnabled) {
        return;
    }
    
    // 检查是否需要切换到备用广告位
    BOOL primaryFailed = !self.isPrimaryAdLoaded || !self.primaryRewardedAd || ![self.primaryRewardedAd isAdReady];
    BOOL secondaryReady = self.isSecondaryAdLoaded && self.secondaryRewardedAd && [self.secondaryRewardedAd isAdReady];
    
    if (primaryFailed && secondaryReady) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 主广告位失败，切换到备用广告位"];
        self.currentAdUnitId = self.currentSecondaryAdUnitId;
        
        // 重新加载主广告位
        [self loadPrimaryRewardedAd];
    }
}

// impressionDataDidSucceed 回调已统一到 WDIronSourceManager 中处理

#pragma mark - 重试机制相关方法

- (void)initializeRetrySettings {
    self.maxRetryCount = 5;           // 最大重试5次
    self.baseRetryInterval = 5.0;     // 基础重试间隔5秒
    self.retryCount = 0;
    self.totalFailureCount = 0;
    self.totalLoadAttempts = 0;
    self.lastRetryTime = 0;
    self.isRetryPaused = NO;
    self.retryTimer = nil;
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试机制初始化完成 - 最大重试次数: %ld, 基础间隔: %.1f秒", (long)self.maxRetryCount, self.baseRetryInterval];
}

- (void)resetRetryState {
    self.retryCount = 0;
    self.isRetryPaused = NO;
    [self cancelRetryTimer];
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试状态已重置"];
}

- (void)scheduleRetryWithDelay:(NSTimeInterval)delay {
    [self cancelRetryTimer];
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 安排 %.1f 秒后重试 (第 %ld/%ld 次)", delay, (long)(self.retryCount + 1), (long)self.maxRetryCount];
    
    __weak typeof(self) weakSelf = self;
    self.retryTimer = [NSTimer scheduledTimerWithTimeInterval:delay repeats:NO block:^(NSTimer * _Nonnull timer) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (strongSelf && !strongSelf.isRetryPaused) {
            [strongSelf performRetry];
        }
    }];
}

- (void)cancelRetryTimer {
    if (self.retryTimer) {
        [self.retryTimer invalidate];
        self.retryTimer = nil;
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试定时器已取消"];
    }
}

- (BOOL)shouldRetry {
    // 检查是否已达到最大重试次数
    if (self.retryCount >= self.maxRetryCount) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 已达到最大重试次数 (%ld), 停止重试", (long)self.maxRetryCount];
        return NO;
    }
    
    // 检查是否被暂停重试
    if (self.isRetryPaused) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 重试已暂停，停止重试"];
        return NO;
    }
    
    // 检查失败率是否过高
    double failureRate = [self calculateFailureRate];
    if (failureRate > 0.8 && self.totalLoadAttempts >= 10) {
        [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 失败率过高 (%.2f%%), 暂停重试", failureRate * 100];
        self.isRetryPaused = YES;
        return NO;
    }
    
    return YES;
}

- (NSTimeInterval)calculateRetryDelay {
    // 指数退避算法: 5秒、10秒、20秒、40秒、80秒
    NSTimeInterval delay = self.baseRetryInterval * pow(2, self.retryCount);
    
    // 限制最大延迟为80秒
    if (delay > 80.0) {
        delay = 80.0;
    }
    
    return delay;
}

- (void)updateFailureStatistics {
    self.totalFailureCount++;
    self.totalLoadAttempts++;
    
    double failureRate = [self calculateFailureRate];
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 失败统计更新 - 总失败: %ld, 总尝试: %ld, 失败率: %.2f%%",
          (long)self.totalFailureCount, (long)self.totalLoadAttempts, failureRate * 100];
}

- (double)calculateFailureRate {
    if (self.totalLoadAttempts == 0) {
        return 0.0;
    }
    return (double)self.totalFailureCount / (double)self.totalLoadAttempts;
}

- (void)performRetry {
    self.retryCount++;
    self.lastRetryTime = [[NSDate date] timeIntervalSince1970];
    
    [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] 执行重试 (第 %ld/%ld 次)", (long)self.retryCount, (long)self.maxRetryCount];
    
    // 根据双广告位模式选择重新加载方式
    if (self.isDualAdEnabled) {
        [self loadDualRewardedAds];
    } else {
        [self loadRV];
    }
}

#pragma mark - 前后台感知（与 WDRewardedVideoManager 风格一致）
- (void)onAppWillResignActive {
    if (self.rvState == WDRVShowing) {
        self.rvBecameInactiveWhileShowing = YES;
    }
}

- (void)onAppDidBecomeActive {
    if (self.rvState == WDRVShowing) {
        self.rvCameBackAfterClick = YES;
        if (self.lastAdInfoForWatchdog) {
            [self restartRVCloseWatchdogWithTimeout:10 adInfo:self.lastAdInfoForWatchdog];
        }
    }
}

#pragma mark - 广告 UI 可见性判断

- (UIViewController *)_topMostViewController {
    UIWindow *keyWindow = nil;
    for (UIWindow *w in UIApplication.sharedApplication.windows) {
        if (w.isKeyWindow) { keyWindow = w; break; }
    }
    if (!keyWindow) keyWindow = UIApplication.sharedApplication.windows.firstObject;
    UIViewController *vc = keyWindow.rootViewController;
    while (vc.presentedViewController) { vc = vc.presentedViewController; }
    return vc;
}
- (BOOL)isAdUIVisible {
    UIViewController *top = [self _topMostViewController];
    if (!top) return NO;
    NSString *cls = NSStringFromClass(top.class).lowercaseString;
    // 按需补充关键字
    return ([cls containsString:@"lpm"] ||
            [cls containsString:@"levelplay"] ||
            [cls containsString:@"ironsource"] ||
            [cls containsString:@"mtg"] ||
            [cls containsString:@"mintegral"]);
}

#pragma mark - 轮询式 Close Watchdog（仅在安全条件下合成 close）
- (void)startRVCloseWatchdogWithTimeout:(NSTimeInterval)timeout adInfo:(LPMAdInfo *)adInfo {
    [self invalidateRVCloseWatchdog];
    self.lastAdInfoForWatchdog = adInfo ?: self.lastAdInfoForWatchdog;
    self.rvClosePollDeadline   = NSDate.date.timeIntervalSince1970 + timeout; // 软超时（需点击返回或已发奖才触发）
    // 设置绝对兜底截止时间，避免无限等待；比软超时更长、更保守
    // 典型激励视频时长 30s 左右，保留 90~120s 足够安全
    self.rvAbsoluteForceCloseDeadline = NSDate.date.timeIntervalSince1970 + 120.0;

    __weak typeof(self) weakSelf = self;
    self.rvClosePoller = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(__unused NSTimer * _Nonnull t) {
        __strong typeof(weakSelf) self = weakSelf;
        if (!self || self.rvState != WDRVShowing) { [self invalidateRVCloseWatchdog]; return; }
        BOOL visible = [self isAdUIVisible];
        NSTimeInterval now = NSDate.date.timeIntervalSince1970;
        // 仅在点击返回后不可见，或已发放奖励后，到达软超时才允许合成 close
        BOOL softCanForceByClick   = (self.rvCameBackAfterClick && !visible && now >= self.rvClosePollDeadline);
        BOOL softCanForceByReward  = (self.receiveRewardForPlacement && now >= self.rvClosePollDeadline);
        // 绝对兜底：长时间仍不可见（或SDK未回调close），为防卡死，超过绝对超时时间才强制合成
        BOOL absoluteForceFallback = (!visible && now >= self.rvAbsoluteForceCloseDeadline);

        if (softCanForceByClick || softCanForceByReward || absoluteForceFallback) {
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ⏰ 兜底检查通过：visible=%d cameBack=%d reward=%d softDeadline=%.0f absDeadline=%.0f now=%.0f -> 合成 close",
             (int)visible, (int)self.rvCameBackAfterClick, (int)self.receiveRewardForPlacement, self.rvClosePollDeadline, self.rvAbsoluteForceCloseDeadline, now];
            [self invalidateRVCloseWatchdog];
            [self didCloseAdWithAdInfo:(self.lastAdInfoForWatchdog)];
            return;
        }

        // 不可见但尚未满足软触发条件：继续等待，避免提前关闭
        if (!visible && now < self.rvClosePollDeadline) {
            [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] ⏰ 兜底检查：广告不可见但未到软超时，继续等待 (剩余%.0fs)", self.rvClosePollDeadline - now];
        }
        // 到达软超时但不满足点击返回/已发奖：顺延软超时 5s，避免误判
        if (now >= self.rvClosePollDeadline && !(self.rvCameBackAfterClick || self.receiveRewardForPlacement)) {
            self.rvClosePollDeadline = now + 5.0;
            [IMLogUtils debug:IMLogTagAd format:@"🎬 [Rewarded] ⏳ 软超时到期但未点击返回/未发奖，顺延 5s"];
        }
        // 到期仍可见：顺延 5s 再判断（避免硬砍）
        if (visible && now >= self.rvClosePollDeadline) {
            self.rvClosePollDeadline = now + 5.0;
            [IMLogUtils info:IMLogTagAd format:@"🎬 [Rewarded] ⏳ 兜底到期但广告仍可见，顺延 5s 再判"];
        }
    }];
}
- (void)restartRVCloseWatchdogWithTimeout:(NSTimeInterval)newTimeout adInfo:(LPMAdInfo *)adInfo {
    // 只更新截止时间，不清空轮询
    self.lastAdInfoForWatchdog = adInfo ?: self.lastAdInfoForWatchdog;
    self.rvClosePollDeadline   = NSDate.date.timeIntervalSince1970 + newTimeout;
}
- (void)invalidateRVCloseWatchdog {
    [self.rvClosePoller invalidate];
    self.rvClosePoller = nil;
    self.rvBecameInactiveWhileShowing = NO;
    self.rvCameBackAfterClick = NO;
}

@end
